

/**
 * Basis iterator class. Holds a collection of objects and provides methods adding and removeing objects and for retrieving those items in sequence.
 * @author Jeremy Wischusen <cortex@visualflowdesigns.com>
 * @version 0.1
 */
class com.vfd.collections.iterators.Iterator
{
	
	//array to hold collection of items
	private var _items:Array;
	
	//loop varaible to indicate if the iteration should loop to begining or end of the collections when one of those bounds has been reached.
	private var _loop:Boolean = false;
	
	//internal index to track which item the iteration is currently on.
	private var _index:Number = 0;
	public function Iterator(items:Array, loop:Boolean)
	{
		if(items)
		{
			this._items = items;
		}
		else
		{
			this._items = new Array();
		}
		if(loop)
		{
			this._loop = loop;
		}
	}
	
	
	//retreival functions
	//get next item
	public function nextItem():Object
	{
		this._index++;
		return this.getItem();
	}
	
	
	//get previous item
	public function prevItem():Object
	{
		this._index--;
		return this.getItem();
	}
	
	private function getItem()
	{
		this.constrainIndex();
		return this._items[this._index];
	}
	
	public function jumpTo(index:Number)
	{
		this._index = index - 1;
		return this.nextItem();
	}
	
	public function getItemAt(index:Number)
	{
		return this._items[index];
	}
	
	
	//add remove functions
	public function set items(items:Array)
	{
		this._items = items;
	}
	
	public function addItems()
	{
		for(var i = 0; i < arguments.length; i++)
		{
			this._items.push(arguments[i]);
		}
	}
	
	public function addItemsAt(index:Number, items:Array)
	{
		this._items.splice(index, 0, items);
	}
	
	public function removeItems()
	{
		for(var i = 0; i < arguments.length; i++)
		{
			if(this._items[i] == arguments[i])
			{
				this._items.splice(i, 1);
			}
		}
	}
	
	public function removeItemAt(index:Number)
	{
		this._items.splice(index, 1);
	}
	
	public function removeRange(start:Number, end:Number)
	{
		var deleteCount:Number = (end - start) + 1;
		this._items.splice(start, deleteCount);
	}
	
	
	//utility functions
	// if loop is set to true, reset the index to the upper or lower bound if they have been exceeded. If loop is false, reset the index to the bound that was exceeded.
	private function constrainIndex()
	{
		if(this._loop)
		{
			if(this._index < 0)
			{
				this._index = this._items.length - 1;
			}
			else if(this._index >= this._items.length)
			{
				this._index = 0;
			}
		}
		else
		{
			if(this._index < 0)
			{
				this._index = 0;
			}
			else if(this._index >= this._items.length)
			{
				this._index = this._items.length - 1;
			}
		}
	}
	
	public function set loop(loop:Boolean)
	{
		this._loop = loop;
	}
	
}
